/// ===========================================================================
/// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
/// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
/// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
/// PURPOSE.
/// ===========================================================================
/// 
/// Project:        MOSS Faceted Search
/// Author:         Leonid Lyublinski (leonidly@microsoft.com)
/// Company:        Microsoft Services
/// Date:           09/17/2007  Version:        1.1
///
/// ===========================================================================

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Microsoft.SharePoint.Portal.ExtendedSearch
{

    internal class FacetMenu : List<FacetCollection>, IComparer<FacetCollection>
    {
        #region Fields
        private Common.FacetSortEnum _sortOrder = Common.FacetSortEnum.Name;
        private int _hits;
        #endregion

        #region Properties
        public Common.FacetSortEnum SortOrder
        {
            get { return _sortOrder; }
            set { _sortOrder = value; }
        }
        public int Hits
        {
            get
            {
                _hits = 0;
                for (int i = 0; i < Count; i++)
                {
                    _hits += this[i].Hits;
                }
                return _hits;
            }
        }
        #endregion

        #region Methods
        public bool ContainsFacetCollection(string facetCollectionName)
        {
            for (int i = 0; i < Count; i++)
            {
                if (this[i].Name.ToLower() == facetCollectionName.ToLower()) return true;
            }
            return false;
        }

        public FacetCollection GetFacetCollection(string facetCollectionName)
        {
            for (int i = 0; i < Count; i++)
            {
                if (this[i].Name.ToLower() == facetCollectionName.ToLower()) return this[i];
            }
            return null;
        }

        public void Sort(System.Collections.Specialized.StringCollection facetColumns)
        {
            int j = 0;
            for (int i = 0; i < facetColumns.Count; i++)
            {
                if (this.ContainsFacetCollection(facetColumns[i])){
                    FacetCollection fc = GetFacetCollection(facetColumns[i]);
                    this.Remove(fc);
                    this.Insert(j, fc);
                    j++;
                }
            }
        }
        #endregion

        #region Constructors
        public FacetMenu()
            : base()
        { }

        public FacetMenu(Dictionary<string, Dictionary<string, Int32>> facetMenu)
            : this()
        {
            foreach (string facetCollectionName in facetMenu.Keys)
            {
                FacetCollection facetCollection = new FacetCollection(facetCollectionName);
                this.Add(facetCollection);

                Dictionary<string, int> facets = facetMenu[facetCollectionName];
                foreach (string facetName in facets.Keys)
                {
                    Facet facet = new Facet(facetName, facets[facetName]);
                    facetCollection.Add(facet);
                }
            }
        }

        #endregion

        #region IComparer<FacetCollection> Members

        public int Compare(FacetCollection x, FacetCollection y)
        {
            switch (_sortOrder)
            {
                case Common.FacetSortEnum.Name:
                    return x.Name.CompareTo(y.Name);

                case Common.FacetSortEnum.Hits:
                    return -1 * x.Hits.CompareTo(y.Hits); // by default DESC

                case Common.FacetSortEnum.Max:
                    return -1 * x.Max.CompareTo(y.Max); // by default DESC
                
                default:
                    return 0;
            }
        }

        #endregion
    }

    internal class FacetCollection : List<Facet>, IComparer<Facet>, ICloneable
    {
        #region Fields
        private Common.FacetSortEnum _sortOrder = Common.FacetSortEnum.None;
        private string _name;
        private int _hits;
        private int _max;
        private Common.PropTypeEnum _dataType;
        #endregion

        #region Properties
        public int Hits
        {
            get
            {
                _hits = 0;
                for (int i = 0; i < Count; i++)
                {
                    _hits += this[i].Hits;
                }
                return _hits;
            }
        }
        public int Max
        {
            get
            {
                for (int i = 0; i < Count; i++)
                {
                    _max = Math.Max(_max, this[i].Hits);
                }
                return _max;
            }
        }
        public Common.FacetSortEnum SortOrder
        {
            get { return _sortOrder; }
            set { _sortOrder = value; }
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public Common.PropTypeEnum DataType
        {
            get { return _dataType; }
            set { _dataType = value; }
        }
        #endregion

        #region Methods
        public bool ContainsFacet(string facetName)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (this[i].Name.ToLower() == facetName.ToLower()) return true;
            }
            return false;
        }
        public bool ContainsFacet(Guid id)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (this[i].ID == id) return true;
            }
            return false;
        }
        public Facet GetFacet(string facetName)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (this[i].Name.ToLower() == facetName.ToLower()) return this[i];
            }
            return null;
        }
        public Facet GetFacet(Guid id)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (this[i].ID == id) return this[i];
            }
            return null;
        }
        #endregion

        #region Constructors
        public FacetCollection()
            : base()
        { }

        public FacetCollection(string name)
            : this()
        {
            _name = name;
        }
        #endregion

        #region IComparer<Facet> Members
        public int Compare(Facet x, Facet y)
        {
            switch (_sortOrder)
            {
                case Common.FacetSortEnum.Name:
                    return x.DisplayName.CompareTo(y.DisplayName);

                case Common.FacetSortEnum.Hits:
                    return -1 * x.Hits.CompareTo(y.Hits); // by default DESC       

                default:
                    return 0;
            }

        }

        #endregion

        #region ICloneable Members
        /// <summary>
        /// Returns deep copy of the object
        /// </summary>
        /// <returns></returns>
        public FacetCollection Clone()
        {
            FacetCollection clone = this;
            return clone;
        }

        #endregion

        #region ICloneable Members

        object ICloneable.Clone()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }

    internal class Facet
    {
        #region Fields
        private string _name;
        private string _displayName;
        private int _hits;
        private string _image;
        private Guid _id;        
        #endregion

        #region Properties
        public Guid ID
        {
            get { return _id; }
        }
        public string Image
        {
            get { return _image; }
            set { _image = value; }
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public string DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }
        public int Hits
        {
            get { return _hits; }
            set { _hits = value; }
        }
        
        #endregion

        #region Constructors
        public Facet(string name, int count)
        {
            _name = name;
            _displayName = name;
            _hits = count;
            _id = Guid.NewGuid();
        }
        public Facet(string name, string displayName, int count):this( name, count)
        {
            _displayName = displayName;
        }
        public Facet(string name, string displayName, int count, string image)
            : this(name, displayName, count)
        {
            _image = image;
        }        
        #endregion
    }

}
